/* (c) 2016 Open Source Geospatial Foundation - all rights reserved
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.security.oauth2;
import java.util.Arrays;
import java.util.List;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.security.oauth2.client.DefaultOAuth2ClientContext;
import org.springframework.security.oauth2.client.OAuth2RestTemplate;
import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails;
import org.springframework.security.oauth2.client.token.AccessTokenProvider;
import org.springframework.security.oauth2.client.token.AccessTokenProviderChain;
import org.springframework.security.oauth2.client.token.grant.client.ClientCredentialsAccessTokenProvider;
import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeAccessTokenProvider;
import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails;
import org.springframework.security.oauth2.client.token.grant.implicit.ImplicitAccessTokenProvider;
import org.springframework.security.oauth2.client.token.grant.password.ResourceOwnerPasswordAccessTokenProvider;
import org.springframework.security.oauth2.common.AuthenticationScheme;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableOAuth2Client;
/**
* GitHub specific REST remplates for OAuth2 protocol.
* <p>
* GitHub Authorization APIs available at <strong>https://developer.github.com/v3/#authentication</strong>
* and <strong>https://developer.github.com/v3/oauth/</strong>
* </p>
* <p>
* First of all the user must create an API key through the GitHub API Credentials <br/>
* See: <string>https://github.com/settings/applications/new</strong>
* </p>
* <p>
* The procedure will provide a new <b>Client ID</b> and <b>Client Secret</b>
* </p>
* <p>
* Also the user must specify the <b>Authorization callback URL</b> pointing to the GeoServer instances <br/>
* Example:
* <ul>
* <li>http://localhost:8080/geoserver</li>
* </ul>
* </p>
* <p>
* The GitHub OAuth2 Filter Endpoint will automatically redirect the users to an URL like the following one at first login <br/>
* <br/>
* <code>
* https://github.com/login/oauth/authorize?response_type=code&client_id=my_client_id&redirect_uri=http://localhost:8080/geoserver&scope=user
* </code>
* </p>
* <p>
* Tipically a correct configuration for the GitHub OAuth2 Provider is like the following:
* </p>
* <ul>
* <li>Cliend Id: <b>my_client_id</b></li>
* <li>Cliend Secret: <b>my_client_secret</b></li>
* <li>Access Token URI: <b>https://github.com/login/oauth/access_token</b></li>
* <li>User Authorization URI: <b>https://github.com/login/oauth/authorize</b></li>
* <li>Redirect URI: <b>http://localhost:8080/geoserver</b></li>
* <li>Check Token Endpoint URL: <b>https://api.github.com/user</b></li>
* <li>Logout URI: <b>https://github.com/logout</b></li>
* <li>Scopes: <b>user</b></li>
* </ul>
*
* @author Alessio Fabiani, GeoSolutions S.A.S.
*/
@Configuration(value="githubOAuth2SecurityConfiguration")
@EnableOAuth2Client
class GitHubOAuth2SecurityConfiguration extends GeoServerOAuth2SecurityConfiguration {
@Bean(name="githubOAuth2Resource")
public OAuth2ProtectedResourceDetails geoServerOAuth2Resource() {
AuthorizationCodeResourceDetails details = new AuthorizationCodeResourceDetails();
details.setId("github-oauth2-client");
details.setGrantType("authorization_code");
details.setAuthenticationScheme(AuthenticationScheme.header);
details.setClientAuthenticationScheme(AuthenticationScheme.form);
return details;
}
/**
* Must have "session" scope
*/
@Bean(name="githubOauth2RestTemplate")
@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
public OAuth2RestTemplate geoServerOauth2RestTemplate() {
OAuth2RestTemplate oAuth2RestTemplate = new OAuth2RestTemplate(geoServerOAuth2Resource(),
new DefaultOAuth2ClientContext(getAccessTokenRequest()));
AuthorizationCodeAccessTokenProvider authorizationCodeAccessTokenProvider = new AuthorizationCodeAccessTokenProvider();
authorizationCodeAccessTokenProvider.setStateMandatory(false);
AccessTokenProvider accessTokenProviderChain = new AccessTokenProviderChain(
Arrays.<AccessTokenProvider> asList(authorizationCodeAccessTokenProvider,
new ImplicitAccessTokenProvider(),
new ResourceOwnerPasswordAccessTokenProvider(),
new ClientCredentialsAccessTokenProvider()));
oAuth2RestTemplate.setAccessTokenProvider(accessTokenProviderChain);
List<HttpMessageConverter<?>> messageConverters = oAuth2RestTemplate.getMessageConverters();
messageConverters.add(new MappingJackson2HttpMessageConverter());
return oAuth2RestTemplate;
}
}